//
//  RCAFNetRequest.m
//  RCNetRequestProject
//
//  Created by kabu on 2017/7/19.
//  Copyright © 2017年 RC. All rights reserved.
//

#import "RCAFNetRequest.h"
#import "AFNetworking.h"

@interface RCAFNetRequest ()
@end
@implementation RCAFNetRequest
+ (instancetype)manager{
    RCAFNetRequest *instanse=[[RCAFNetRequest alloc]initWithRequestSerialization:[RCHttpRequestSerialization serializer] responseSerialization:[RCHttpResponseSerialization serializer]];
    return instanse;
}
-(instancetype)init{
    self= [super init];
    if (self) {
        
    }
    return self;
}
-(instancetype)initWithRequestSerialization:(id<RCURLRequestSerialization>)aReqSerialization responseSerialization:(id<RCURLResponseSerialization>)aRepSerializaiton{
    self = [super init];
    if (self) {
        [self setupRequestSerialization:aReqSerialization responseSerialization:aRepSerializaiton];
    }
    return self;
}
- (void)setupRequestSerialization:(id<RCURLRequestSerialization>)aReqSerialization responseSerialization:(id<RCURLResponseSerialization>)aRepSerializaiton{
    self.requestSerialization=aReqSerialization;
    self.responseSerialization=aRepSerializaiton;
}
-(AFHTTPSessionManager*)httpManager{
    AFHTTPSessionManager *manager;
    if ([[self serverHostUrl] hasPrefix:@"https"]) {
        NSURL *url=[NSURL URLWithString:[self serverHostUrl]];
        manager = [[AFHTTPSessionManager manager] initWithBaseURL:url];
        if (self.isAllowHttps) {
            AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
            securityPolicy.allowInvalidCertificates=YES;
            [securityPolicy setValidatesDomainName:NO];
            if ([self serverCerData]) {
                NSSet *set=[NSSet setWithObject:[self serverCerData]];
                securityPolicy=[AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:set];
                securityPolicy.allowInvalidCertificates=NO;
                [securityPolicy setValidatesDomainName:YES];
            }
            
            
            manager.securityPolicy = securityPolicy;
        }
    }else{
        manager=[AFHTTPSessionManager manager];
    }
    
    //设置相关AF请求和返回处理
    if ([self.requestSerialization isKindOfClass:[RCJsonRequestSerialization class]]) {
        manager.requestSerializer=[AFJSONRequestSerializer serializer];
        
    }else if([self.requestSerialization isKindOfClass:[RCHttpRequestSerialization class]]){
        manager.requestSerializer = [AFHTTPRequestSerializer serializer];
    }
    if ([self.responseSerialization isKindOfClass:[RCJSONResponseSerialization class]]) {
        RCJSONResponseSerialization *ser=(RCJSONResponseSerialization*)self.responseSerialization;
        NSSet *set=ser.acceptableContentTypes;
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        [manager.responseSerializer setAcceptableContentTypes:set];
        
    }else if ([self.responseSerialization isKindOfClass:[RCHttpResponseSerialization class]]){
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    }
    [self transformHttpHeaderToAF:manager];
    return manager;
}
-(AFURLSessionManager*)urlManager{
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *urlManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    if (self.isAllowHttps) {
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
        securityPolicy.allowInvalidCertificates=YES;
        [securityPolicy setValidatesDomainName:YES];
        urlManager.securityPolicy = securityPolicy;
    }
    //设置AF相关返回处理
    if ([self.responseSerialization isKindOfClass:[RCJSONResponseSerialization class]]) {
        urlManager.responseSerializer = [AFJSONResponseSerializer serializer];
    }
    return urlManager;
}
-(void)transformHttpHeaderToAF:(AFHTTPSessionManager*)manager{
    RCHttpRequestSerialization *rcSerialization=self.requestSerialization;
    NSDictionary *dict=[rcSerialization httpRequestHeaders];
    if (dict) {
        [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            //
            [manager.requestSerializer setValue:obj forHTTPHeaderField:key];
        }];
        
    }
}

#pragma mark RCNetRequest
- (id)getWithUrl:(NSString *)url params:(id)params success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    
    AFHTTPSessionManager *manager=[self httpManager];
    NSLog(@"req url : %@ \n  params: %@",url,params);
    NSURLSessionDataTask *task= [manager GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
        //
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"resp: %@",responseObject);
        if (aSuccess) {
            aSuccess(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"resp error : %@",error);
        if (aFailure) {
            aFailure(error);
        }
    }];
    return task;
}
- (id)postWithUrl:(NSString *)url params:(id)params success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    
    AFHTTPSessionManager *manager=[self httpManager];
    NSLog(@"req url : %@ \n  params: %@",url,params);
    NSURLSessionDataTask *task=[manager POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
        //
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"resp: %@",responseObject);
        if (aSuccess) {
            aSuccess(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"resp error : %@",error);
        if (aFailure) {
            aFailure(error);
        }
    }];
    return task;
}
- (id)putWithUrl:(NSString *)url params:(id)params success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    AFHTTPSessionManager *manager=[self httpManager];
    NSURLSessionDataTask *task=[manager PUT:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        //
        if (aSuccess) {
            aSuccess(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //
        if (aFailure) {
            aFailure(error);
        }
    }];
    return task;
}
- (id)deleteWithUrl:(NSString *)url params:(id)params success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    AFHTTPSessionManager *manager=[self httpManager];
    NSURLSessionDataTask *task=[manager DELETE:url parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        //
        if (aSuccess) {
            aSuccess(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //
        if (aFailure) {
            aFailure(error);
        }
    }];
    return task;
}
- (id)downloadWithUrl:(NSString *)url params:(id)params atLocal:(NSURL *)aLocal success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    NSError *error;
    AFURLSessionManager *manager = [self urlManager];
    NSMutableURLRequest *req = [self requestWithMethod:nil URLString:url parameters:params error:&error];
    NSURLSessionDownloadTask *task= [manager downloadTaskWithRequest:req progress:^(NSProgress * _Nonnull downloadProgress) {
        //
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        //
        NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
        return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        //
        if (!error) {
            if (aSuccess) {
                aSuccess(filePath);
            }
        }else{
            if (aFailure) {
                aFailure(error);
            }
        }
    }];
    [task resume];
    return task;
}
- (id)uploadWithUrl:(NSString *)url params:(id)params withLocal:(NSURL *)wLocal success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    NSError *error;
    AFURLSessionManager *manager = [self urlManager];
    
    NSMutableURLRequest *req = [self requestWithMethod:nil URLString:url parameters:params error:&error];
    
    NSURLSessionUploadTask *task = [manager uploadTaskWithRequest:req fromFile:wLocal progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (!error) {
            if (aSuccess) {
                aSuccess(responseObject);
            }
        }else{
            if (aFailure) {
                aFailure(error);
            }
        }
    }];
    [task resume];
    return task;
}

-(id)postWithUrl:(NSString *)url params:(id)params formData:(NSData *)aFormData mimeType:(NSString *)mimeType fileName:(NSString *)fileName name:(NSString *)name success:(RCNetRequestSuccessBlock)aSuccess failure:(RCNetRequestFailureBlock)aFailure{
    
    AFHTTPSessionManager *manager =[self httpManager];
    NSURLSessionDataTask*task=[manager POST:url parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        //
        if (aFormData) {
            [formData appendPartWithFileData:aFormData name:name fileName:fileName mimeType:mimeType];
        }
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        //
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        //
        if (aSuccess) {
            aSuccess(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //
        if (aFailure) {
            aFailure(error);
        }
    }];
    [task resume];
    return  task;
}
@end
